package com.cy.pj.sys.service.aspect;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.sys.pojo.SysLog;
import com.cy.pj.sys.service.SysLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Slf4j
@Aspect
@Component
public class TestSysLogAspect {

    @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
    private void testLog(){}

    @Around("testLog()")
    public Object testSysLog(ProceedingJoinPoint jp) throws Throwable {
        long t1 = System.currentTimeMillis();
        log.info("start{}:",t1);
        try{
            Object result = jp.proceed();
            long t2 = System.currentTimeMillis();
            log.info("after{}:",t2);
            testLogTests(jp,t2-t1,null);
            return result;

        } catch (Throwable e) {
            e.printStackTrace();
            long t3 = System.currentTimeMillis();
            testLogTests(jp,t3-t1,e);
            throw e;
        }
    }

    @Autowired
    private SysLogService sysLogService;
    public void testLogTests(ProceedingJoinPoint jp,Long time,Throwable e) throws Exception {
        //1.获取日志属性
        String username = "dio";//获取用户名
        String ip = "123,456,789,1011";//获取ip地址
        Class<?> targetCls = jp.getTarget().getClass();//获取jp反射类的实例
        MethodSignature mc = (MethodSignature) (jp.getSignature());//获取方法签名
        Method targetMethod = targetCls.getDeclaredMethod(mc.getName(), mc.getParameterTypes());//获取方法
        RequiredLog requiredLog = targetMethod.getAnnotation(RequiredLog.class);//获取注解
        String annotation = requiredLog.operation();//获取注解名
        String classMethodName = targetCls.getName()+"."+targetMethod.getName();//获取方法全路径名
        Object[] args = jp.getArgs();//获取类中的所有参数
        String params = new ObjectMapper().writeValueAsString(args);//将所有参数转换为json字符串
        //2.设置日志属性
        SysLog sysLog = new SysLog();
        sysLog.setUsername(username);
        sysLog.setIp(ip);
        sysLog.setMethod(classMethodName);
        sysLog.setOperation(annotation);
        sysLog.setParams(params);
        sysLog.setCreatedTime(new Date());
        sysLog.setTime(time);
        if(e!=null){
            sysLog.setStatus(0);
            sysLog.setError(e.getMessage());
        }
        //3.将日志写入数据库
        log.info("log{}:",new ObjectMapper().writeValueAsString(sysLog));
        sysLogService.saveLog(sysLog);
    }
}
